﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Oops.Xna.Framework.Graphics
{
	/// <summary>
	/// Defines a timed event during the playing of an <see cref="AnimationClip"/>.
	/// </summary>
	[Serializable()]
	public class AnimationEvent : IEquatable<AnimationEvent>, IComparable<AnimationEvent>
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="AnimationEvent"/> class.
		/// </summary>
		/// <param name="time">The time of the <see cref="AnimationEvent"/>.</param>
		public AnimationEvent(TimeSpan time)
		{
			this.Time = time;
		}

		/// <summary>
		/// Initializes a new instances of the <see cref="AnimationEvent"/> class.
		/// </summary>
		/// <param name="time">The time of the <see cref="AnimationEvent"/>.</param>
		/// <param name="state">The state of the <see cref="AnimationEvent"/>.</param>
		public AnimationEvent(TimeSpan time, object state)
		{
			this.Time = time;
			this.State = state;
		}

		/// <summary>
		/// Gest the time of the <see cref="AnimationEvent"/>.
		/// </summary>
		public TimeSpan Time { get; private set; }
		
		/// <summary>
		/// Gets or sets a state of the <see cref="AnimationEvent"/>.
		/// </summary>
		public object State { get; set; }

		#region IEquatable<AnimationEvent> Members

		bool IEquatable<AnimationEvent>.Equals(AnimationEvent other)
		{
			return 
				other != null && 
				other.Time == this.Time && 
				other.State == this.State;
		}

		#endregion

		#region IComparable<AnimationEvent> Members

		int IComparable<AnimationEvent>.CompareTo(AnimationEvent other)
		{
			// The events are equal.
			if (this.Time == other.Time)
			{
				return 0;
			}

			// The time if greater than the specified event's time.
			if (this.Time >= other.Time)
			{
				return 1;
			}

			// The time is less than the specified event's time.
			return -1;

		}

		#endregion

		#region Object Members

		public override bool Equals(object obj)
		{
			return this.Equals(obj as AnimationEvent);
		}

		public override int GetHashCode()
		{
			return this.Time.GetHashCode();
		}

		#endregion

		public static bool operator ==(AnimationEvent a, AnimationEvent b)
		{
			// Get null status.
			bool aIsNull = (object)a == null;
			bool bIsNull = (object)b == null;

			// Check for null status.
			if (aIsNull || bIsNull)
			{
				return aIsNull == bIsNull;
			}

			// Check for equality.
			return a.Equals(b);
		}

		public static bool operator !=(AnimationEvent a, AnimationEvent b)
		{
			// Get null status.
			bool aIsNull = (object)a == null;
			bool bIsNull = (object)b == null;
			
			// Check for null status.
			if (aIsNull || bIsNull)
			{
				return aIsNull != bIsNull;
			}

			// Check for inequality.
			return a.Time != b.Time || a.State != b.State;
		}
	}
}
